package ccm.tools;

import ccm.component.override.VFlowLayout;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;


public class GenerateFont extends JFrame implements ActionListener
{
    protected final JButton   addJButton;
    protected final JCheckBox sameFileJCheckBox;
    protected final JButton   generateJButton;
    protected final JPanel    fontJPanes;


    public GenerateFont()
    {
        super("GenerateFont");
        setSize(1400,900);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setLayout(new BorderLayout());

        JPanel configJPanel=new JPanel();
        add(configJPanel,BorderLayout.NORTH);
        configJPanel.setLayout(new FlowLayout(FlowLayout.LEFT));

        addJButton=new JButton("添加");
        configJPanel.add(addJButton);
        addJButton.addActionListener(this);

        sameFileJCheckBox=new JCheckBox("生成到同一文件",true);
        configJPanel.add(sameFileJCheckBox);
        sameFileJCheckBox.addActionListener(this);
        sameFileJCheckBox.setSelected(true);

        generateJButton=new JButton("生成");
        configJPanel.add(generateJButton);
        generateJButton.addActionListener(this);

        fontJPanes=new JPanel();
        this.add(fontJPanes,BorderLayout.CENTER);
        fontJPanes.setLayout(new VFlowLayout());

        fontJPanes.add(new FontJPanel("宋体","SimSun",12,0,-2));
        fontJPanes.add(new FontJPanel("宋体","SimSun",16,0,-2));
        fontJPanes.add(new FontJPanel("宋体","SimSun",24,0,-3));
        fontJPanes.add(new FontJPanel("宋体","SimSun",32,0,-4));


        setVisible(true);
    }

    public static void main(String[] args) throws IOException
    {
        new GenerateFont();
    }

    public void actionPerformed(ActionEvent e)
    {
        if(e.getSource().equals(addJButton))
        {
            fontJPanes.add(new FontJPanel());
            fontJPanes.updateUI();
            fontJPanes.invalidate();
            fontJPanes.validate();
            fontJPanes.repaint();
        }
        else if(e.getSource().equals(generateJButton))
        {
            generateJButton.setEnabled(false);
            try
            {
                BufferedWriter outC=new BufferedWriter(new FileWriter("ScnsLcd.font.c"));
                BufferedWriter outH=new BufferedWriter(new FileWriter("ScnsLcd.font.h"));
                BufferedWriter other=new BufferedWriter(new FileWriter("other.c"));

                outC.write("#include \"ScnsLcd.h\"\n#if defined(SCNS_LCD_ENABLE)&&SCNS_LCD_ENABLE==1\n");
                outH.write("#ifndef __SCNS_LCD_FONT_H__\n#define __SCNS_LCD_FONT_H__\n#include \"ScnsLcd.h\"\n#if defined(SCNS_LCD_ENABLE)&&SCNS_LCD_ENABLE==1\n");

                for(Component com: fontJPanes.getComponents())
                    if(com instanceof FontJPanel)
                        ((FontJPanel)com).generate(outC,outH,other);

                outC.write("#endif\n");
                outH.write("#endif\n#endif\n");

                outC.close();
                outH.close();
                other.close();

                JOptionPane.showMessageDialog(this,"已生成","已生成",JOptionPane.PLAIN_MESSAGE);
                generateJButton.setText("生成");
            }catch(IOException ex)
            {
                ex.printStackTrace();
                JOptionPane.showMessageDialog(this,"IO错误","生成失败",JOptionPane.ERROR_MESSAGE);
            }
            generateJButton.setEnabled(true);

            //            JFileChooser jFileChooser=new JFileChooser("");
            //            jFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
            //            jFileChooser.showDialog(new JLabel(),"选择");
            //            smctp.receiveData(new ReceiveDataEvent(this,FileSaver.readAll(jFileChooser.getSelectedFile())));
        }
    }

    private class FontJPanel extends JPanel implements ActionListener, ChangeListener
    {
        protected final JButton           deleteJButton;
        protected final JCheckBox         allJCheckBox;
        protected final JCheckBox         asciiJCheckBox;
        protected final JCheckBox         gbkJCheckBox;
        protected final JTextField        textJTextField;
        protected final JPanel            viewJPanel;
        protected final JSpinner          sizeJSpinner;
        protected final JSpinner          xBiasJSpinner;
        protected final JSpinner          yBiasJSpinner;
        protected final JTextField        outNameJTextField;
        protected final JComboBox<String> fontTypeJComboBox;
        private         int               cnt;


        FontJPanel()
        {
            this("","",12,0,0);
        }

        FontJPanel(String fontType,String outName,int size,int xBias,int yBias)
        {
            super();
            setLayout(new FlowLayout(FlowLayout.LEFT));
            add(new JLabel("字体:"));
            fontTypeJComboBox=new JComboBox<String>(GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames());
            add(fontTypeJComboBox);
            fontTypeJComboBox.setSelectedItem(fontType);
            fontTypeJComboBox.addActionListener(this);

            add(new JLabel("名字:"));
            outNameJTextField=new JTextField(outName,8);
            add(outNameJTextField);

            add(new JLabel("字体大小:"));
            sizeJSpinner=new JSpinner(new SpinnerNumberModel(size,1,64,1));
            add(sizeJSpinner);
            sizeJSpinner.addChangeListener(this);

            add(new JLabel("左右偏移:"));
            xBiasJSpinner=new JSpinner(new SpinnerNumberModel(xBias,-64,64,1));
            add(xBiasJSpinner);
            xBiasJSpinner.addChangeListener(this);

            add(new JLabel("上下偏移:"));
            yBiasJSpinner=new JSpinner(new SpinnerNumberModel(yBias,-64,64,1));
            add(yBiasJSpinner);
            yBiasJSpinner.addChangeListener(this);

            allJCheckBox=new JCheckBox("生成全部字体",true);
            add(allJCheckBox);
            allJCheckBox.addActionListener(this);
            allJCheckBox.setSelected(true);

            asciiJCheckBox=new JCheckBox("包含ASCII",true);
            add(asciiJCheckBox);
            asciiJCheckBox.addActionListener(this);
            asciiJCheckBox.setSelected(true);

            gbkJCheckBox=new JCheckBox("包含GBK",true);
            add(gbkJCheckBox);
            gbkJCheckBox.addActionListener(this);
            gbkJCheckBox.setSelected(true);

            textJTextField=new JTextField("火星大王",8);
            add(textJTextField);
            textJTextField.setEnabled(false);
            textJTextField.addActionListener(this);


            deleteJButton=new JButton("删除");
            add(deleteJButton);
            deleteJButton.addActionListener(this);

            viewJPanel=new JPanel();
            add(viewJPanel);
            viewJPanel.setLayout(new FlowLayout());
            viewJPanel.setBackground(new Color(0X444444));
            updateViewJPanel();
        }

        private void updateViewJPanel()
        {
            viewJPanel.removeAll();
            final String str=allJCheckBox.isSelected()?"火星大王HXDW1234":textJTextField.getText();
            for(int i=0;i<str.length();++i)
            {
                final String word=str.substring(i,i+1);
                viewJPanel.add(new JLabel(new ImageIcon(generateArray(null,word,true))));
            }
            viewJPanel.updateUI();
            viewJPanel.invalidate();
            viewJPanel.validate();
            viewJPanel.repaint();
        }

        private BufferedImage generateArray(BufferedWriter out,String word,boolean newLine)
        {
            if(word.length()!=1)
                throw new RuntimeException();
            System.out.println(word);
            final int fontSize=(Integer)sizeJSpinner.getValue();
            final int width=(word.getBytes().length==1)?(fontSize/2):(fontSize);
            final int yBias=(Integer)yBiasJSpinner.getValue();
            final int xBias=(Integer)xBiasJSpinner.getValue();
            final String fontType=(String)fontTypeJComboBox.getSelectedItem();

            BufferedImage image=new BufferedImage(width,fontSize,BufferedImage.TYPE_INT_RGB);
            Graphics2D g=image.createGraphics();
            g.setFont(new Font(fontType,Font.PLAIN,fontSize));
            g.drawString(word,xBias,fontSize+yBias);

            if(out!=null)
                for(int i=0;i<image.getHeight();++i)
                {
                    for(int j=0, k=0, b=0;j<image.getWidth();++j)
                    {
                        b|=((image.getRGB(j,i)==-1)?1:0)<<k;
                        ++k;
                        if(j==image.getWidth()-1||k==8)
                        {
                            try
                            {
                                out.write(String.format("0X%02X,",b));
                                k=0;
                                b=0;
                                ++cnt;
                                if((cnt%24)==0&&newLine)
                                    out.write("\n        ");
                            }catch(IOException ex)
                            {
                                ex.printStackTrace();
                            }
                        }
                    }
                }
            return image;
        }

        public void actionPerformed(ActionEvent e)
        {
            if(e.getSource().equals(deleteJButton))
            {
                fontJPanes.remove(this);
                fontJPanes.updateUI();
                fontJPanes.invalidate();
                fontJPanes.validate();
                fontJPanes.repaint();
            }
            else if(e.getSource().equals(allJCheckBox))
            {
                textJTextField.setEnabled(!allJCheckBox.isSelected());
                asciiJCheckBox.setEnabled(allJCheckBox.isSelected());
                gbkJCheckBox.setEnabled(allJCheckBox.isSelected());
            }
            updateViewJPanel();
        }

        @Override
        public void stateChanged(ChangeEvent e)
        {
            updateViewJPanel();
        }

        private void generate(BufferedWriter outC,BufferedWriter outH,BufferedWriter other) throws IOException
        {
            if(allJCheckBox.isSelected())
                generate(outC,outH);
            else
                generate(other);
        }

        private void generate(BufferedWriter outC,BufferedWriter outH) throws IOException
        {
            final int fontSize=(Integer)sizeJSpinner.getValue();
            final String name=outNameJTextField.getText();

            outH.write("extern const ScnsLcdFont scnsLcdFont"+name+fontSize+";\n");
            outC.write("const ScnsLcdFont scnsLcdFont"+name+fontSize+"={\n");
            outC.write("    .fontSize="+fontSize+",\n");
            outC.write("    .name=\""+name+"\",\n");
            if(asciiJCheckBox.isSelected())
            {
                outC.write("    .ascii=(const uint8[]){\n        ");
                for(int i=' ';i<=(int)'~';++i)
                    generateArray(outC,new String(new byte[]{(byte)i},"GBK"),true);

                outC.write("\n    },\n");
            }

            if(gbkJCheckBox.isSelected())
            {
                outC.write("#if defined(SCNS_LCD_FONT_USE_GBK) && SCNS_LCD_FONT_USE_GBK ==1\n");
                outC.write("    .gbk=(const uint8[]){\n        ");

                for(int i=0X81;i<=0XFE;++i)
                {
                    for(int j=0X40;j<=0X7E;++j)
                        generateArray(outC,new String(new byte[]{(byte)i,(byte)j},"GBK"),true);
                    for(int j=0X80;j<=0XFE;++j)
                        generateArray(outC,new String(new byte[]{(byte)i,(byte)j},"GBK"),true);
                }
                outC.write("\n    },\n");
                outC.write("#endif\n");
            }

            outC.write("};\n");
        }

        private void generate(BufferedWriter other) throws IOException
        {
            final String str=textJTextField.getText();
            if(str.length()!=0)
            {
                final int fontSize=(Integer)sizeJSpinner.getValue();
                final String name=outNameJTextField.getText()+fontSize;
                other.write("//"+str+"\n");
                other.write(" static const uint8 "+name+"[]={\n");
                BufferedImage img=null;
                boolean sameSize=true;
                for(int i=0;i<str.length();++i)
                {
                    other.write("    ");
                    final String word=str.substring(i,i+1);
                    final BufferedImage tmp=generateArray(other,word,false);
                    if(img==null)
                        img=tmp;
                    sameSize&=(tmp.getHeight()==img.getHeight()&&tmp.getWidth()==img.getWidth());
                    other.write("//"+word+"\n");
                }
                other.write("};\n");
                if(sameSize)
                    other.write("scnsLcdDisplayRawChar(SCNS_LCD_LAYER_0,(Point){0,0},"+name+","+str.length()+","+img.getHeight()+","+img.getWidth()+",SCNS_LCD_COLOR_GREEN,SCNS_LCD_COLOR_BACKGROUND,0);\n");
            }
        }

    }
}
